/*LICENSE_BEGIN
 * ******************************************************************
 * Copyright 2006 by the Dainamite Robocup-Team at the
 * DAI-Labor, TU-Berlin (www.dai-labor.de)
 * 
 * Members of Dainamite are:
 * Holger Endert
 * Robert Wetzker
 * Thomas Karbe
 * Axel Heßler
 * Philippe Bütter
 * Felix Brossmann
 * 
 * Licensed under the GNU GPL (General Public License) Free Software 
 * License, Version 2. You may use this file only in compliance with 
 * the License. You may obtain a copy of the License at:
 * 
 * http://www.fsf.org/licensing/licenses/gpl.txt
 * ******************************************************************
LICENSE_END*/
package robocup.component.tactics;

import java.util.Arrays;

import robocup.component.ControllerNumbers;
import robocup.component.SConf;
import robocup.component.ControllerNumbers.PLAY_MODE;
import robocup.component.ControllerNumbers.STAMINA_LEVEL;
import robocup.component.actionfactories.BasicActionFactory;
import robocup.component.actionfactories.TurnNeckActionFactory;
import robocup.component.actions.Action.TYPE;
import robocup.component.situations.InterceptBallSituation;
import robocup.component.worldobjects.Player;

/**
 * The state for intercepting the ball. This state is triggered when the player
 * can not kick the ball and is the one of the fastest player to the ball.
 * Most of the logic used here can be found in the 
 * {@link InterceptBallSituation}. 
 *
 * @see InterceptBallSituation
 */
public class InterceptBallState extends AbstractState {

  /**
   * the fastest opponent to the ball.
   */
	private Player fastestOpponent;

  /**
   * my interception time.
   */
	private int myInterceptionTime;

  /**
   * the fastest opponent's interception time.
   */
	private int opponentInterceptionTime;

	/**
	 * Simple state that defines ball-interception.
	 * 
	 * @param parent -
	 *            the StateEvaluation (parent) object
	 */
	public InterceptBallState(StateEvaluation parent) {

		super(parent);
		this.state = STATES.INTERCEPT_BALL;
	}

	/**
	 * Always go when fastest teammate to the ball.
   * 
   * (This is a very simple version. Add your logic here!)
	 */
	@Override
	public boolean preCondition() {

		if (!this.checkPlayMode() || !this.getBall().isReliable()
				|| this.getPlayer().canKick(getWorld().getBallRef())) {
			return false;
		}

		// on kick-off set true for player 10
		if (PLAY_MODE.KICK_OFF_OWN == getWorld().getPlayMode()
				&& getPlayer().getNumber() == 10) {
			return true;
		}

		return this.getProphet().getFastestTeammateToBall() != null &&
      this.getProphet().getFastestTeammateToBall().isMe();
	}

	/**
	 * Probability is always 1.
	 */
	@Override
	protected double successProbability() {

		return 1;
	}

	/**
	 * Benefit is always 0.95 except when the ball is already kickabl.
	 */
	@Override
	protected double successBenefit() {

		if (this.checkPlayerHasBall()
				&& this.getPlayer().equals(this.getWorld().getSelfRef())) {
			return this.getProphet().getInterceptBallBenefit();
		}

		return 0.95;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see robocup.component.tactics.AbstractState#calculateMainAction()
	 */
	public void calculateMainAction() {

		if (getWorld().getPlayMode() == PLAY_MODE.PLAY_ON
				&& (mainAction = getProphet().getNextInterceptAction(
						this.getPlayer())) != null) {

			// if ball goes out anyway we don't have to hurry
			if (this.getProphet().ballOutBeforeIntercept()
					&& !this.getProphet().ballWillGoIntoOwnGoal()
					&& mainAction.getType() == TYPE.DASH) {
				this.getWorld().getSelfRef().correctDashPower(mainAction,
						STAMINA_LEVEL.HIGH);
			}
		} else {
			mainAction = BasicActionFactory.moveToPos(getWorld(), getWorld()
					.getBallRef().getPosition(),
					ControllerNumbers.STAMINA_LEVEL.MEDIUM);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see robocup.component.tactics.AbstractState#calculateTurnNeckAction()
	 */
	public void calculateTurnNeckAction() {
    
    //ball old -> watch ball
		if (this.getWorld().getBallRef().getAge(this.getWorld().getBodyCycle(),
						robocup.component.worldobjects.Ball.UPDATE_MODE.SEEN_WITHOUT_SPEED) > 2) {
			turnNeckAction = TurnNeckActionFactory.getAction(this.getWorld(),
					state, mainAction, viewModeAction, this
							.getWorld().getBallRef());
			return;
		}

    //opponent intercepting as well -> watch opponent from time to time
		if (this.myInterceptionTime > this.opponentInterceptionTime - 5) {
			double[] weights = new double[23];
			Arrays.fill(weights, 0);

			weights[22] = 1;
			if (this.fastestOpponent != null)
				weights[this.fastestOpponent.getNumber() - 1 + 11] = 0.5;

			turnNeckAction = TurnNeckActionFactory.getAction(getWorld(), state,
					mainAction, viewModeAction, weights);
		}
    
		// before getting the ball watch in the direction of the opp. goal
		else if (this.myInterceptionTime == 1
				&& this.getWorld().getAgeOfPoint(
						SConf.getInstance().GOAL_POS_OTHER) > 2
				&& this.getWorld().getOpponentsGoalie() != null) {
			double[] weights = new double[23];
			Arrays.fill(weights, 0);

			weights[this.getWorld().getOpponentsGoalie().getNumber() + 11 - 1] = 1;

			turnNeckAction = TurnNeckActionFactory.getAction(getWorld(), state,
					mainAction, viewModeAction, weights);
		} else {
			super.calculateTurnNeckAction();
		}
	}

}
